#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

// 消息队列结构体
struct msgbuf{
	long mtype; // 标识位
	char mtext[1024]; // 数据位
};

// 线程任务函数
void *func(void *arg)
{
	int msgid = *((int *)arg);
	// 定义消息队列结构体变量
	struct msgbuf recv_buf;
	while(1)
	{
		memset(&recv_buf, 0, sizeof(recv_buf));
		msgrcv(msgid, &recv_buf, sizeof(recv_buf), 1, 0); // 接收标识为1
		printf("当前收到的消息=%s\n", recv_buf.mtext);
		if(strcmp(recv_buf.mtext, "bye") == 0)
			break;
	}
	printf("子线程退出了！\n");
	// 销毁消息队列
	// msgctl(msgid, IPC_RMID, NULL);
	// pthread_exit(NULL);
	exit(0); // 程序的任意位置调用，都能够，使得进程退出
}

int main(int argc, char const *argv[])
{
	// 1.创建键值
	key_t key = ftok(".", 1);
	if(key == -1)
	{
		perror("ftok error\n");
		return -1;
	}
	// 2.获取消息队列的id号
	int msgid = msgget(key, IPC_CREAT|IPC_EXCL|0666);
	if(msgid == -1 && errno == EEXIST)
	{
		msgid = msgget(key, 0666);
	}
	if(msgid == -1)
	{
		perror("msgget error\n");
		return -1;
	}

	// 消息发送和接收
	struct msgbuf send_buf;
	send_buf.mtype = 2;

	// 创建线程
	pthread_t tid;
	pthread_create(&tid, NULL, func, (void *)&msgid);

	while(1)
	{
		// 清空
		memset(send_buf.mtext, 0, sizeof(send_buf.mtext));
		printf("请输入需要发送的内容\n");
		scanf("%s", send_buf.mtext);
		// 发送
		msgsnd(msgid, &send_buf, sizeof(send_buf), 0);
		if(strcmp(send_buf.mtext, "bye")==0)
			break;
	}
	/* // 等待子线程退出，不关注子线程退出值
	printf("准备等子线程\n");
	pthread_join(tid, NULL);
	printf("等到子线程\n"); */

	pthread_cancel(tid); // 取消子线程

	// 销毁消息队列
	msgctl(msgid, IPC_RMID, NULL);

	return 0;
}
